package com.nineclock.approve.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.approve.dto.*;
import com.nineclock.approve.mapper.ApproveDefinitionMapper;
import com.nineclock.approve.pojo.ApproveDefinition;
import com.nineclock.approve.service.ActivitiService;
import com.nineclock.approve.service.ApproveDefinitionService;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.JsonUtils;
import com.nineclock.common.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Service
@Slf4j
public class ApproveDefinitionServiceImpl implements ApproveDefinitionService {


    @Autowired
    ApproveDefinitionMapper approveDefinitionMapper;

    @Override
    public List<ApproveGroupDefinitionDto> queryApproveGroupDefinition() {

        List<ApproveGroupDefinitionDto> list = new ArrayList<>();

        //查询所有的审批流程对象
        LambdaQueryWrapper<ApproveDefinition> approveDefinitionQw = new LambdaQueryWrapper<>();
        approveDefinitionQw.eq(ApproveDefinition::getCompanyId, CurrentUserHolder.get().getCompanyId());
        approveDefinitionQw.eq(ApproveDefinition::getIsValid, "1");
        //获取 该企业的所有的有效审批流程对象
        List<ApproveDefinition> approveDefinitionList = approveDefinitionMapper.selectList(approveDefinitionQw);
        if(CollectionUtil.isNotEmpty(approveDefinitionList)){
            //按照group_type进行分类
            Map<String, List<ApproveDefinition>> map = approveDefinitionList.stream().collect(Collectors.groupingBy(ApproveDefinition::getGroupType));
            //map集合中的 key 的集合
            Set<String> keySets = map.keySet();

            for (String key : keySets) {
                //一个key对应  一个 ApproveGroupDefinitionDto
                ApproveGroupDefinitionDto definitionDto = new ApproveGroupDefinitionDto();
                //key对应 groupType  类型属性
                definitionDto.setGroupType(key);
                //value 对应 审批流程列表
                definitionDto.setDefinitionList(map.get(key));
                list.add(definitionDto);
            }
        }


        return list;
    }


    @Autowired
    ActivitiService activitiService;
    /**
     *
     * 新增 / 修改
     * @param approveDefinitionSaveDto
     */
    @Override
    public void saveApproveDefinition(ApproveDefinitionSaveDto approveDefinitionSaveDto) {
        //判断是否有 id， 如果有id是修改，没有id是新增
        if(approveDefinitionSaveDto == null || approveDefinitionSaveDto.getBaseData() == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //基础数据
        ApproveDefinitionBaseDataDto baseData = approveDefinitionSaveDto.getBaseData();
        if(baseData.getId() == null){
            //新增
            //把前端传过来的基本数据赋值给 审批定义对象
            ApproveDefinition definition = BeanHelper.copyProperties(baseData, ApproveDefinition.class);

            //设置允许访问的人员
            List<AllowUserObjDto> allowUserJson = baseData.getAllowUserJson();
            definition.setAllowUserJson(JsonUtils.toString(allowUserJson));

            //表单信息
            List<ApproveDefinitionTableDataDto> tableData = approveDefinitionSaveDto.getTableData();
            definition.setFormJson(JsonUtils.toString(tableData));

            //流程 json， 需要流程的每一个节点中添加一个唯一的标识（nodeKey）
            // json转换为 JSONArray, 给json数组中的每一个JSONObject添加一个节点 nodeKey
            String flowData = approveDefinitionSaveDto.getFlowData();
            JSONArray jsonArray = JSONUtil.parseArray(flowData);
            //扩展 nodeKey节点
            expandParamWithNodeKey(jsonArray);
            definition.setFlowJson(JsonUtils.toString(jsonArray));

            //设置一个唯一的表名
            definition.setTableName("flow" + UUIDUtils.getUUID());

            //获取 审批表单字段信息
            List<ColumnObjDto> columnObjDtos = expandFieldKey(approveDefinitionSaveDto);
            definition.setColumns(JsonUtils.toString(columnObjDtos));

            //设置基础字段
            definition.setIsValid("1");
            definition.setCreateTime(new Date());
            definition.setDataFrom("1"); // 1 来源是 自定义
            definition.setCompanyId(CurrentUserHolder.get().getCompanyId() + "");

            approveDefinitionMapper.insert(definition);

            // 部署到 工作流 中
            activitiService.deployProcessToActiviti(definition);
        }else{
            //修改
            String id = baseData.getId();
            //先根据id ， 查询审批流程对象
            ApproveDefinition definition = approveDefinitionMapper.selectById(id);
            definition.setUpdateTime(new Date());

            //获取 审批表单字段信息
            List<ColumnObjDto> columnObjDtos = expandFieldKey(approveDefinitionSaveDto);
            definition.setColumns(JsonUtils.toString(columnObjDtos)); //表单的 字段定义

            //流程 json， 需要流程的每一个节点中添加一个唯一的标识（nodeKey）
            // json转换为 JSONArray, 给json数组中的每一个JSONObject添加一个节点 nodeKey
            String flowData = approveDefinitionSaveDto.getFlowData();
            JSONArray jsonArray = JSONUtil.parseArray(flowData);
            //扩展 nodeKey节点
            expandParamWithNodeKey(jsonArray);
            definition.setFlowJson(JsonUtils.toString(jsonArray)); //流程json对象


            List<AllowUserObjDto> allowUserJson = baseData.getAllowUserJson();
            definition.setAllowUserJson(JsonUtils.toString(allowUserJson));//运行访问的用户的json


            //表单信息
            List<ApproveDefinitionTableDataDto> tableData = approveDefinitionSaveDto.getTableData();
            definition.setFormJson(JsonUtils.toString(tableData)); //表单的json对象
            //执行更新操作
            approveDefinitionMapper.updateById(definition);

            //后续操作：需要更新到acitiviti 工作流中
            //删除之前的流程
            activitiService.dropProcessToActiviti(definition);
            //部署新的流程
            activitiService.deployProcessToActiviti(definition);
        }


    }

    @Override
    public ApproveDefinitionResultDto queryById(String id) {

        //创建返回值对象
        ApproveDefinitionResultDto resultDto = new ApproveDefinitionResultDto();
        if(id == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //根据id获取流程定义对象
        ApproveDefinition definition = approveDefinitionMapper.selectById(id);
        //把definition对象转换为 ApproveDefinitionResultDto
        //设置基础字段对象
        ApproveDefinitionBaseDataDto baseData = BeanHelper.copyProperties(definition, ApproveDefinitionBaseDataDto.class);
        String allowUserJson = definition.getAllowUserJson();
        //可以把json转换为list集合
        List<AllowUserObjDto> allowUserObjDtos = JsonUtils.toList(allowUserJson, AllowUserObjDto.class);
        baseData.setAllowUserJson(allowUserObjDtos);

        //设置 表单信息
        String formJson = definition.getFormJson();
        List<ApproveDefinitionTableDataResultDto> tableDataResultDtos = JsonUtils.toList(formJson, ApproveDefinitionTableDataResultDto.class);


        String flowJson = definition.getFlowJson();


        resultDto
                .setBaseData(baseData)
                .setTableData(tableDataResultDtos)
                .setFlowData(flowJson);

        return resultDto;
    }

    /**
     * 扩充参数 : fieldKey
     * @param approveDefinitionDto
     * @return
     */
    private List<ColumnObjDto> expandFieldKey(ApproveDefinitionSaveDto approveDefinitionDto) {
        List<ColumnObjDto> columns = new ArrayList<>();

        for (ApproveDefinitionTableDataDto tableData : approveDefinitionDto.getTableData()) {
            if(StrUtil.isEmpty(tableData.getFieldKey())){
                tableData.setFieldKey(UUIDUtils.getUUID());
            }

            columns.add(new ColumnObjDto(tableData.getFieldKey(), tableData.getLab(), tableData.getTitle(), "1"));
        }
        return columns;
    }

    private void expandParamWithNodeKey(JSONArray jsonArray) {
        for(int i = 0; i < jsonArray.size(); i++){
            JSONObject jsonNode = (JSONObject) jsonArray.get(i);

            String nodeKey = jsonNode.getStr("nodeKey");
            if(StrUtil.isEmpty(nodeKey)){
                jsonNode.put("nodeKey", UUIDUtils.getUUID());
            }

            //处理网关节点的内部节点 nodeKey
            String type = jsonNode.getStr("type");
            if("condition".equals(type)){

                JSONArray batchArray = (JSONArray) jsonNode.get("node");
                if(batchArray!=null && batchArray.size()>0){

                    for (int j = 0; j < batchArray.size(); j++) {
                        JSONArray innerArray = (JSONArray) batchArray.get(j);

                        if(innerArray!=null && innerArray.size()>0){
                            for (int k = 0; k < innerArray.size(); k++) {
                                JSONObject node = (JSONObject) innerArray.get(k);
                                if(!node.containsKey("nodeKey")){
                                    node.put("nodeKey", UUIDUtils.getUUID());
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
